function varargout = TLDiscreteIntegratorDlg(action,varargin)

% TL_DISCRETEINTEGRATOR_DLG manages the user interface for TargetLink Discrete Integrator block
%
% SYNTAX dlgInfo = TLDiscreteintegratorDlg('GetDlgInfo');
%   gets dialog info of TargetLink Discrete Integrator block
%
%   INPUT ARGUMENTS
%   -/-
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLDiscreteintegratorDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLDiscreteintegratorDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLDiscreteintegratorDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLDiscreteintegratorDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLDiscreteintegratorDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLDiscreteintegratorDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_SimBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.16 $
% $Date: 2011/07/21 17:02:01MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action
    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'Discrete-Time Integrator';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        dlgInfo.pageNames   = {
            'Output'...
            'States'...
            'Limits'...
            'Logging & Autoscaling'...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);
        
    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'Output'
                [sheetDims, ctrlPos] = ...
                    FcnCalcOutputControlPositions(commonGeom);
                
            case 'States'
                [sheetDims,ctrlPos] = FcnCalcStatesControlPositions(commonGeom);
                
            case 'Limits'
                [sheetDims,ctrlPos] = FcnCalcLimitsControlPositions(commonGeom);
                
            case 'Logging & Autoscaling'
                excludedCtrls = {};
                [sheetDims, ctrlPos] = ...
                    TLManageLoggingCtrls('calcCtrls', commonGeom, sheetDims, excludedCtrls);
                
            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 1;
                [sheetDims,ctrlPos] = ...
                    TLManageDocCtrls('ctrlpos',commonGeom,sheetDims,bCodeComment,bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;
        
    case 'Create',
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName, dlgdata.pageNames, 'exact');
        switch pageName
            case 'Output'
                dlgdata = FcnCreateOutputControls(pageNum, dlgfig, dlgdata);
                
            case 'States'
                dlgdata = FcnCreateStatesControls(pageNum, dlgfig, dlgdata);
                
            case 'Limits'
                dlgdata = FcnCreateLimitsControls(pageNum, dlgfig, dlgdata);
                
            case 'Logging & Autoscaling'
                dlgdata = TLManageLoggingCtrls('create',pageNum,dlgfig,dlgdata);
                
            case 'Documentation'
                dlgdata = TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;
        
    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');
        switch pageName
            case 'Output'
                [dlgdata, bModified] = ...
                    FcnManageOutputControls(pageNum, dlgfig, dlgdata, pageAction);
                
            case 'States'
                [dlgdata,bModified] = ...
                    FcnManageStatesControls(pageNum, dlgfig, dlgdata, pageAction);
                
            case 'Limits'
                [dlgdata, bModified] = ...
                    FcnManageLimitsControls(pageNum, dlgfig, dlgdata, pageAction);
                
            case 'Logging & Autoscaling'
                [dlgdata, bModified] = ...
                    TLManageLoggingCtrls('manage', pageNum, dlgdata, pageAction, 'logdata');
                
            case 'Documentation'
                [dlgdata, bModified] = ...
                    TLManageDocCtrls('callback', pageNum, dlgfig, ...
                    dlgdata, pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;
        
    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;
        
    case 'Update'
        dlgfig    = varargin{1};
        dlgdata   = varargin{2};
        pageNum   = varargin{3};
        
        pageName  = dlgdata.pageNames{pageNum};
        
        switch pageName
            case 'Output'
                dlgdata = FcnUpdateOutputControls(dlgdata, dlgfig, pageNum);
                
            case 'States'
                dlgdata = FcnUpdateStatesControls(dlgdata, dlgfig, pageNum);
                
            case 'Limits'
                dlgdata = FcnUpdateLimitsControls(dlgdata, dlgfig, pageNum);
                
            case 'Logging & Autoscaling'
                dlgdata =  TLManageLoggingCtrls('update',pageNum,dlgdata,'logdata','output');
                TLManageLoggingCtrls('setCtrls',pageNum, dlgfig, dlgdata);
                
            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout{1} = dlgdata;
        
    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;
        
    otherwise
        error(['Invalid action: "' action '"']);
end


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        [codefile,blockstr] = get_codefile(dlgdata.model);
        if ~isempty(codefile)
            codeedit(codefile,blockstr);
        end
        
    case 'ViewCode'
        switch dlgdata.pageNames{dlgdata.CurrentPageNum}
            case 'States'
                blockVar{1} = 'state';
                blockVar{2} = 'input';
                idx = get(dlgdata.pageData{2}.children.selectPopup,'Value');
                tl_create_links_to_model('ShowComputation',dlgdata.model, blockVar{idx});
            case 'Limits'
                blockVar{1} = 'upperlimit';
                blockVar{2} = 'lowerlimit';
                idx = get(dlgdata.pageData{2}.children.selectPopup,'Value');
                tl_create_links_to_model('ShowDeclaration',dlgdata.model, blockVar{idx});
            otherwise
                blockVar = 'output';
                tl_create_links_to_model('ShowComputation',dlgdata.model, blockVar);
        end
        
    otherwise
        error('Invalid callback');
        
end % switch(action)


%-----------------------------------------------------------------------------------------
% FcnCalcOutputControlPositions calculates positions for all controls on output page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcOutputControlPositions(commonGeom)

excludedCtrls = {'width', 'element', 'saturate', 'scalarExp', ...
    'inheritproperties'};
[sheetDims, ctrlPos, col, colDelta] = ...
    tl_calc_ctrls_positions(commonGeom,excludedCtrls);

% integration options
strings_and_styles = {
    'backward Euler  ',    'popupmenu';
    'External reset:',     'text';
    'falling  ',           'popupmenu';
    'Saturation port'      'checkbox';
    'Sample time:',        'text';
    repmat('0',1,16),      'edit'};

[integratorPopupSize ...
    resetLabelSize, ...
    resetPopupSize, ...
    satportCheckboxSize, ...
    stepsizeLabelSize, ...
    stepsizeEditSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

%---------------------------------------
% all controls lie in one row
%---------------------------------------
cy = commonGeom.frameBottomEdgeBuffer;

% integration method label
cx = col(1);
ctrlPos.integrationLabel = [cx cy ctrlPos.descLabel(3:4)];

% integration method popup
cx = col(2);
ctrlPos.integrationPopup = [cx cy integratorPopupSize];

% external reset label
cx = cx + integratorPopupSize(1) + colDelta / 3;
ctrlPos.resetLabel = [cx cy resetLabelSize];

% external reset popup
cx = cx + resetLabelSize(1) + colDelta / 3;
ctrlPos.resetPopup = [cx cy resetPopupSize];

% saturation port checkbox
cx = max(cx + resetPopupSize(1) + colDelta / 3, col(5));
ctrlPos.satportCheckbox = [cx cy satportCheckboxSize];

% sample time edit
cx = col(8) + ctrlPos.unitEdit(3) - stepsizeEditSize(1);
ctrlPos.stepsizeEdit = [cx cy stepsizeEditSize];

% sample time label
cx = cx - stepsizeLabelSize(1) - 5;
ctrlPos.stepsizeLabel = [cx cy stepsizeLabelSize];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) + ...
    + ctrlPos.addoptGroupbox(4);


%-----------------------------------------------------------------------------------------
% FcnCreateOutputControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputControls(pageNum, dlgfig, dlgdata)

% create standard controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, dlgdata);

Children = dlgdata.pageData{pageNum}.children;
ctrlPos  = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};
% create the addoptGroupbox which will contain integrator options
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Integrator options'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% integration controls
Children.integrationLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Integration:', ...
    'Position',           ctrlPos.integrationLabel);

Children.integrationPopup = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'popupmenu', ...
    'String',             {'forward Euler'}, ...
    'Position',           ctrlPos.integrationPopup, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''integrationPopup'')',pageName));

Children.resetLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'External reset:', ...
    'Position',           ctrlPos.resetLabel);

Children.resetPopup = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'popupmenu', ...
    'String',             {'none'}, ...
    'Position',           ctrlPos.resetPopup, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''resetPopup'')',pageName));

Children.satportCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'String',             'Saturation port', ...
    'Style',              'checkbox', ...
    'Position',           ctrlPos.satportCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''satportCheckbox'')',pageName));

% stepsize controls
Children.stepsizeLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Sample time:', ...
    'Position',           ctrlPos.stepsizeLabel);

Children.stepsizeEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.stepsizeEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''nameEdit'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageOutputControls manages control actions of output page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageOutputControls(pageNum, dlgfig, dlgdata, pageAction)

Children  = dlgdata.pageData{pageNum}.children;

switch pageAction
    
    case 'integrationPopup'
        dlgdata.data.integrationmethod = ...
            get(Children.integrationPopup, 'Value');
        bModified = 1;
        
    case 'resetPopup'
        dlgdata.data.state.externalreset = ...
            get(Children.resetPopup, 'Value');
        bModified = 1;
        
    case 'satportCheckbox'
        dlgdata.data.state.showsaturation = ...
            get(Children.satportCheckbox, 'Value');
        bModified = 1;
        
    case 'stepsizeEdit'
        stepsizestr = get(Children.stepsizeEdit, 'String');
        if ~isempty(stepsizestr)
            dlgdata.data.dt = stepsizestr;
        else
            beep;
        end
        bModified = 1;
        
    otherwise
        [dlgdata, bModified1] = ...
            TLManageVariableCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, 'output');
        [dlgdata, bModified2] = ...
            TLManageScalingCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, 'output');
        bModified = bModified1 || bModified2;
end


%--------------------------------------------------------------------------
% FcnUpdateOutputControls updates the controls of the output tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOutputControls(dlgdata,dlgfig,pageNum)

% update standard controls
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, 'output');
dlgdata = TLManageScalingCtrls('update', pageNum, dlgdata, 'output', []);

enumStruct = tl_manage_blockset('GetEnums');
idx = strcmp({enumStruct.name},'IntegrationMethodEnum');
integrationMethodEnums = enumStruct(idx).strings; 
integrationMethodValues = enumStruct(idx).validvalues; 
idx = strcmp({enumStruct.name},'ExternalResetEnum');
externalResetEnums = enumStruct(idx).strings;
externalResetValues = enumStruct(idx).validvalues;

stepsizeEditCtrlStatus = struct('enable', 'on', 'string', '');
integrationPopupCtrlStatus = struct('enable', 'on', 'string', '');
resetPopupCtrlStatus = struct('enable', 'on', 'string', '');
satportCheckboxCtrlStatus = struct('enable', 'on');

stepsizeEditCtrlStatus.string = dlgdata.data.dt;
if any(dlgdata.data.integrationmethod == integrationMethodValues)
    integrationPopupCtrlStatus.value = dlgdata.data.integrationmethod;
    integrationPopupCtrlStatus.string = integrationMethodEnums(integrationMethodValues);
else
    integrationPopupCtrlStatus.iserror = 1;
    integrationPopupCtrlStatus.value = numel(integrationMethodValues)+1;
    integrationPopupCtrlStatus.string = [integrationMethodEnums(integrationMethodValues); integrationMethodEnums(dlgdata.data.integrationmethod)];
end
integrationPopupCtrlStatus.string = strrep(integrationPopupCtrlStatus.string, 'Integration: ', '');
if any(dlgdata.data.state.externalreset == externalResetValues)
    resetPopupCtrlStatus.value = dlgdata.data.state.externalreset;
    resetPopupCtrlStatus.string = externalResetEnums(externalResetValues);
else
    resetPopupCtrlStatus.iserror = 1;
    resetPopupCtrlStatus.value = numel(externalResetValues)+1;
    resetPopupCtrlStatus.string = [externalResetEnums(externalResetValues); externalResetEnums(dlgdata.data.state.externalreset)];
end
satportCheckboxCtrlStatus.value = dlgdata.data.state.showsaturation;

ctrlsList = {'integrationPopup', 'resetPopup', ...
    'satportCheckbox', 'stepsizeEdit'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = dlgdata.pageData{pageNum}.children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

% set controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLSetCtrlsStatus(dlgfig, dlgdata.pageData{pageNum}.children, ...
    ctrlsList);


%-----------------------------------------------------------------------------------------
% FcnCalcStatesControlPositions calculates positions for all controls on state page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcStatesControlPositions(commonGeom)

excludedCtrls = {'type', 'scaling', 'width', 'element', ...
    'inheritproperties', 'allscaling', 'scalarExp'};
[sheetDims, ctrlPos, col, colDelta, rowDelta] = ...
    tl_calc_ctrls_positions(commonGeom,excludedCtrls);

% determine sizes for further controls
strings_and_styles = {
    'Select:',              'text';
    'Initial condition:',   'text';
    'External Source',      'checkbox';
    'Use value of Data Dictionary variable',    'checkbox'};

[selectLabelSize, ...
    initConditionLabelSize, ...
    externSrcCheckboxSize, ...
    useDDValueCheckboxSize] = ...
    ds_get_uicontrol_sizes(commonGeom, strings_and_styles);

%-----------------------------------------------------------
% enlarge groupboxes
%-----------------------------------------------------------
% calculate extra space needed for select popup
dy = commonGeom.editHeight + rowDelta;

% enlarge tlcgGroupbox and move addoptGroupbox
ctrlPos.tlcgoptGroupbox(4) = ctrlPos.tlcgoptGroupbox(4) ...
    + dy;
ctrlPos.addoptGroupbox(2)   = ctrlPos.addoptGroupbox(2) ...
    + dy;

%-----------------------------------------------------------
% supplement tlcgGroupbox
%-----------------------------------------------------------
cy = ctrlPos.descLabel(2) + commonGeom.editHeight + rowDelta;

% select label
cx = col(1);
ctrlPos.selectLabel = [cx cy selectLabelSize];

% select popup
cx = col(2);
ctrlPos.selectPopup = [cx cy ctrlPos.addressEdit(3:4)];

%---------------------------------------
% enlarge width groupbox
%---------------------------------------
% define new height for addoptGroupbox
ctrlPos.addoptGroupbox(4) = commonGeom.editHeight ...
    + commonGeom.checkboxHeight ...
    + rowDelta ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;

%---------------------------------------
% 2nd row
cy = commonGeom.frameBottomEdgeBuffer;

% ddv checkbox
cx = col(1) + initConditionLabelSize(1) + colDelta / 3;
ctrlPos.useDDValueCheckbox = [cx, cy, useDDValueCheckboxSize];

%---------------------------------------
% 1st row
cy = cy + commonGeom.checkboxHeight + rowDelta;

% initial value label
cx = col(1);
ctrlPos.initConditionLabel = [cx cy initConditionLabelSize];

% initial condition edit field
cx = cx + initConditionLabelSize(1) + colDelta / 3;
ctrlPos.initConditionEdit = [cx cy ctrlPos.varEdit(3:4)];

% external source checkbox
cx = cx + ctrlPos.initConditionEdit(3) + colDelta;
ctrlPos.externSrcCheckbox = [cx cy externSrcCheckboxSize];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) ...
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight ...
    + dy;


%-----------------------------------------------------------------------------------------
% FcnCreateStatesControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateStatesControls(pageNum, dlgfig, dlgdata)

% invoke standard function to create variable controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
% no scaling controls

Children = dlgdata.pageData{pageNum}.children;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};

% modify panel title
set(dlgdata.pageData{pageNum}.children.tlcgoptGroupbox, 'Title', 'State options');

% select controls
Children.selectLabel = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'String',             'Select:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.selectLabel);

Children.selectPopup = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'Style',              'Popupmenu', ...
    'String',             {''}, ...
    'BackgroundColor',    'w', ...
    'Position',           ctrlPos.selectPopup, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''selectPopup'')',pageName));

% create the addoptGroupbox which will contain initial condition
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Initial condition'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% initial value controls
Children.initConditionLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Initial condition:', ...
    'Position',           ctrlPos.initConditionLabel);

Children.initConditionEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'BackgroundColor',    'w', ...
    'Style',              'edit', ...
    'Position',           ctrlPos.initConditionEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''initConditionEdit'')',pageName));

Children.externSrcCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'String',             'External source', ...
    'Style',              'checkbox', ...
    'Position',           ctrlPos.externSrcCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''externSrcCheckbox'')',pageName));

Children.useDDValueCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'String',             'Use value of Data Dictionary variable', ...
    'Style',              'checkbox', ...
    'Position',           ctrlPos.useDDValueCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''useDDValueCheckbox'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageStatesControls manages control actions of state page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageStatesControls(pageNum, dlgfig, dlgdata, pageAction)

Children = dlgdata.pageData{pageNum}.children;

selectIdx = get(Children.selectPopup, 'Value');
switch selectIdx
    case 1
        field = 'state';
    case 2
        field = 'input';
end

switch pageAction
    case 'initConditionEdit'
        % field == 'state', the input state has no initial condition
        initialStr = deblank(get(Children.initConditionEdit, 'String'));
        if ~isempty(initialStr)
            if strcmp(initialStr, 'ddv')
                if isempty(dlgdata.data.state.variable)
                    beep;
                else
                    dlgdata.data.state.initial = ['ddv(''', dlgdata.data.state.variable, ''')'];
                    dlgdata.data.state.useddvariablevalue = true;
                end
            else
                dlgdata.data.state.initial = initialStr;
            end
        else
            beep;
        end
        bModified = 1;
        
    case 'externSrcCheckbox'
        % field == 'state', this checkbox is disabled for the input state
        dlgdata.data.state.initialconditionsource = ...
            get(Children.externSrcCheckbox, 'Value') + 1;
        bModified = 1;
        
    case 'selectPopup'
        bModified = 1;
        
    case 'useDDValueCheckbox'
        if get(Children.useDDValueCheckbox, 'Value')
            dlgdata.data.state.initial = ['ddv(''', dlgdata.data.state.variable, ''')'];
            dlgdata.data.state.useddvariablevalue = true;
        else
            dlgdata.data.state.useddvariablevalue = false;
        end
        bModified = true;
        
    otherwise
        [dlgdata, bModified] = TLManageVariableCtrls('manage', ...
            pageNum, dlgfig, dlgdata, pageAction, field);
        % no scaling controls
end


%--------------------------------------------------------------------------
% FcnUpdateStatesControls updates the controls of the states tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateStatesControls(dlgdata, dlgfig, pageNum)

Children = dlgdata.pageData{pageNum}.children;

initConditionEditCtrlStatus = struct('enable', 'on');
externSrcCheckboxCtrlStatus = struct('enable', 'on');
selectPopupCtrlStatus = struct('enable', 'on', ...
    'string', {{'Integrator state', 'Input state'}}, ...
    'value', 1);

selectIdx = get(Children.selectPopup, 'Value');

if dlgdata.data.integrationmethod == 3
    % Trapezoidal method: two state variables (integrator and input state)
    selectPopupCtrlStatus.value = selectIdx;
else
    % Euler methods need only one state variable: deactivate selection
    % control
    selectPopupCtrlStatus.enable = 'inactive';
    selectIdx = 1;
end

% Handle extern source checkbox and initial value edit control
initConditionEditCtrlStatus.string = dlgdata.data.state.initial;
initConditionEditCtrlStatus.enable = flag2str(selectIdx == 1 && ...
    dlgdata.data.state.initialconditionsource == 1);
externSrcCheckboxCtrlStatus.value = ...
    dlgdata.data.state.initialconditionsource == 2 && selectIdx == 1;
externSrcCheckboxCtrlStatus.enable = flag2str(selectIdx == 1);
useDDValueCheckboxCtrlStatus.enable = flag2str(selectIdx == 1 && ...
    ~isempty(dlgdata.data.state.variable));
useDDValueCheckboxCtrlStatus.value = dlgdata.data.state.useddvariablevalue;
if strcmp(initConditionEditCtrlStatus.enable, 'on') && dlgdata.data.state.useddvariablevalue
    initConditionEditCtrlStatus.enable = 'inactive';
end

% Check width
if selectIdx == 1 && dlgdata.data.state.initialconditionsource == 1
    initValue = tl_ensure_param_vector(dlgdata.data.state.initial);
    if isempty(initValue) || length(initValue) > 1
        initConditionEditCtrlStatus.iserror = 1;
    end
end

fields = {'state', 'input'};
field = fields{selectIdx};

dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, field);
% no scaling controls

ctrlsList = {'initConditionEdit', 'selectPopup', 'externSrcCheckbox', 'useDDValueCheckbox'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

% set controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLSetCtrlsStatus(dlgfig, Children, ctrlsList);


%-----------------------------------------------------------------------------------------
% FcnCalcLimitsControlPositions calculates positions for all controls on limits page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcLimitsControlPositions(commonGeom)

excludedCtrls = {'width', 'scalarExp', 'element', ...
    'saturate', 'inheritproperties'};
[sheetDims, ctrlPos, col, colDelta, rowDelta] =...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

strings_and_styles = {
    'Select:',        'text';
    'Lower:',         'text';
    ' Scale Limit ',  'pushbutton';
    'Use value of Data Dictionary variable',    'checkbox'};

[selectLabelSize, ...
    limitLabelSize, ...
    autoscaleButtonSize, ...
    useDDValueCheckboxSize] = ...
    ds_get_uicontrol_sizes(commonGeom, strings_and_styles);

% calculate extra space needed for select popup
dy = commonGeom.editHeight + rowDelta;

% enlarge tlcgGroupbox and move addoptGroupbox
ctrlPos.tlcgoptGroupbox(4) = ctrlPos.tlcgoptGroupbox(4) + dy;
ctrlPos.addoptGroupbox(2)  = ctrlPos.addoptGroupbox(2)  + dy;

% enlarge addoptGroupbox
ctrlPos.addoptGroupbox(4) = commonGeom.editHeight ...
    + commonGeom.checkboxHeight ...
    + rowDelta ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;

% supplement tlcgGroupbox
cy = ctrlPos.descLabel(2) + commonGeom.editHeight + rowDelta;

% select label
cx = col(1);
ctrlPos.selectLabel = [cx cy selectLabelSize];

% select popup
cx = col(2);
ctrlPos.selectPopup = [cx cy ctrlPos.lsbEdit(3:4)];

% lower limit autoscale button
cx = col(7);
ctrlPos.limitScaleButton = [cx,cy, autoscaleButtonSize];

%---------------------------------------
% 2nd row
cy = commonGeom.frameBottomEdgeBuffer;

% ddv checkbox for lower limit
cx = col(2);
ctrlPos.llDDValueCheckbox = [cx, cy, useDDValueCheckboxSize];

% ddv checkbox for upper limit
cx = col(6);
ctrlPos.ulDDValueCheckbox = [cx, cy, useDDValueCheckboxSize];

%---------------------------------------
% 1st row
cy = cy + commonGeom.checkboxHeight + rowDelta;

% lower limit label
cx = col(1);
ctrlPos.llLabel = [cx cy limitLabelSize];

% lower limit edit field
cx = col(2);
ctrlPos.llEdit = [cx cy ctrlPos.varEdit(3:4)];

% upper limit label
cx = col(6) - limitLabelSize(1) - colDelta / 3;
ctrlPos.ulLabel = [cx cy limitLabelSize];

% upper limit edit field
cx = col(6);
ctrlPos.ulEdit = [cx cy ctrlPos.varEdit(3:4)];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) ...
    + commonGeom.editHeight + rowDelta ... % for select popup
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight;


%-----------------------------------------------------------------------------------------
% FcnCreateLimitsControls creates the limits page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateLimitsControls(pageNum, dlgfig, dlgdata)

% create standard controls, upper limit initially
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, dlgdata);

Children = dlgdata.pageData{pageNum}.children;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};
% variable select controls
Children.selectLabel = uicontrol( ...
    'Parent',           Children.tlcgoptGroupbox, ...
    'String',           'Select:', ...
    'Style',            'text', ...
    'Position',         ctrlPos.selectLabel);

Children.selectPopup = uicontrol( ...
    'Parent',           Children.tlcgoptGroupbox, ...
    'Style',            'Popupmenu', ...
    'String',           {'upperlimit', 'lowerlimit'}, ...
    'BackgroundColor',  'w', ...
    'Position',         ctrlPos.selectPopup, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''selectPopup'')',pageName));

% autoscale buttons
Children.limitScaleButton = uicontrol( ...
    'Parent',           Children.tlcgoptGroupbox, ...
    'Style',            'pushbutton', ...
    'String',           'Scale Limit', ...
    'Position',         ctrlPos.limitScaleButton, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''limitScaleButton'')',pageName));

% create the addoptGroupbox which will contain limits options
Children.addoptGroupbox = uipanel( ...
    'Parent',           dlgfig, ...
    'Title',            {'Limits'}, ...
    'Units',            'pixels', ...
    'Position',         ctrlPos.addoptGroupbox);

% lower limit controls
Children.llLabel = uicontrol( ...
    'Parent',           Children.addoptGroupbox, ...
    'String',           'Lower:', ...
    'Style',            'text', ...
    'Position',         ctrlPos.llLabel);

Children.llEdit = uicontrol( ...
    'Parent',           Children.addoptGroupbox, ...
    'Style',            'edit', ...
    'BackgroundColor',  'w', ...
    'Position',         ctrlPos.llEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''llEdit'')',pageName));

% upper limit controls
Children.ulLabel = uicontrol( ...
    'Parent',           Children.addoptGroupbox, ...
    'String',           'Upper:', ...
    'Style',            'text', ...
    'Position',         ctrlPos.ulLabel);

Children.ulEdit = uicontrol( ...
    'Parent',           Children.addoptGroupbox, ...
    'Style',            'edit', ...
    'BackgroundColor',  'w', ...
    'Position',         ctrlPos.ulEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''ulEdit'')',pageName));

Children.llDDValueCheckbox = uicontrol( ...
    'Parent',           Children.addoptGroupbox, ...
    'String',           'Use value of Data Dictionary variable', ...
    'Style',            'checkbox', ...
    'Position',         ctrlPos.llDDValueCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''llDDValueCheckbox'')',pageName));

Children.ulDDValueCheckbox = uicontrol( ...
    'Parent',           Children.addoptGroupbox, ...
    'String',           'Use value of Data Dictionary variable', ...
    'Style',            'checkbox', ...
    'Position',         ctrlPos.ulDDValueCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''ulDDValueCheckbox'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageLimitsControls manages control actions of limit page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageLimitsControls(pageNum, dlgfig, dlgdata, pageAction)

Children = dlgdata.pageData{pageNum}.children;
selectIdx = get(Children.selectPopup,'Value');
switch selectIdx
    case 1
        field = 'upperlimit';
    case 2
        field = 'lowerlimit';
end

switch pageAction
    
    case {'llEdit', 'ulEdit'}
        if strncmp(pageAction, 'll', 2)
            varName = 'lowerlimit';
        else
            varName = 'upperlimit';
        end
        limitStr = deblank(get(Children.(pageAction), 'String'));
        if ~isempty(limitStr)
            if strcmp(limitStr, 'ddv')
                if isempty(dlgdata.data.(varName).variable)
                    beep;
                else
                    dlgdata.data.(varName).value = ['ddv(''', dlgdata.data.(varName).variable, ''')'];
                    dlgdata.data.(varName).useddvariablevalue = true;
                end
            else
                dlgdata.data.(varName).value = limitStr;
            end
        else
            beep;
        end
        bModified = true;
        
    case 'selectPopup'
        bModified = true;
        
    case 'limitScaleButton'
        options.selectDatatypeSign = 'yes';
        options.minimizeWordWidth  = 'yes';
        ds_error_none;
        [dlgdata.data, bModified, msgstruct] = tl_scale_parameters( ...
            dlgdata.model, dlgdata.data, options, field);
        ds_error_register(msgstruct);
        ds_msgdlg('Update', ...
            'Title', ['Scaling of ' get_tlsubsystempath(dlgdata.model) '->' field], ...
            'ShowErrors','yes', ...
            'ShowNotes','yes', ...
            'ShowWarnings','yes');
        
    case {'llDDValueCheckbox', 'ulDDValueCheckbox'}
        if strncmp(pageAction, 'll', 2)
            varName = 'lowerlimit';
        else
            varName = 'upperlimit';
        end
        if get(Children.(pageAction), 'Value')
            dlgdata.data.(varName).value = ['ddv(''', dlgdata.data.(varName).variable, ''')'];
            dlgdata.data.(varName).useddvariablevalue = true;
        else
            dlgdata.data.(varName).useddvariablevalue = false;
        end
        bModified = true;
        
    otherwise
        [dlgdata, bModified1] = ...
            TLManageVariableCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, field);
        
        [dlgdata, bModified2] = ...
            TLManageScalingCtrls('manage', pageNum, dlgfig, dlgdata, pageAction, field);
        
        bModified = bModified1 || bModified2;
end


%--------------------------------------------------------------------------
% FcnUpdateLimitsControls updates the controls of the limit tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateLimitsControls(dlgdata, dlgfig, pageNum)

Children = dlgdata.pageData{pageNum}.children;

% default control status
ulEditCtrlStatus = struct('enable', 'on', 'string', '');
llEditCtrlStatus = struct('enable', 'on', 'string', '');
limitScaleButtonCtrlStatus = struct('enable', 'on');
selectPopupCtrlStatus = struct('enable', 'on', ...
    'string', {{'upperlimit', 'lowerlimit'}}, ...
    'value', 1);

selectIdx = get(Children.selectPopup, 'Value');
switch selectIdx
    case 1
        field = 'upperlimit';
    case 2
        field = 'lowerlimit';
end

% invoke standard update methods
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, field);
upperlimitValue = tl_ensure_param_vector(dlgdata.data.upperlimit.value);
lowerlimitValue = tl_ensure_param_vector(dlgdata.data.lowerlimit.value);
ulEditCtrlStatus.iserror = isempty(upperlimitValue) || length(upperlimitValue) > 1;
llEditCtrlStatus.iserror = isempty(lowerlimitValue) || length(lowerlimitValue) > 1;
constraint = [];
bCompliant = 1;
switch selectIdx
    case 1
        if length(upperlimitValue) == 1
            constraint = upperlimitValue;
        else
            bCompliant = 0;
        end
    case 2
        if length(lowerlimitValue) == 1
            constraint = lowerlimitValue;
        else
            bCompliant = 0;
        end
end
dlgdata = TLManageScalingCtrls('update', pageNum, dlgdata, field, constraint);

% set status for simulated values and autoscale button
simulatedLabelCtrlStatus = tl_get_control_userdata(Children.simulatedLabel);
lowerSimulatedValueCtrlStatus = tl_get_control_userdata(Children.lowerSimulatedValue);
upperSimulatedValueCtrlStatus = tl_get_control_userdata(Children.upperSimulatedValue);

% status of ddv checkboxes
llDDValueCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.lowerlimit.variable));
llDDValueCheckboxCtrlStatus.value = dlgdata.data.lowerlimit.useddvariablevalue;
if dlgdata.data.lowerlimit.useddvariablevalue
    llEditCtrlStatus.enable = 'inactive';
end
ulDDValueCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.upperlimit.variable));
ulDDValueCheckboxCtrlStatus.value = dlgdata.data.upperlimit.useddvariablevalue;
if dlgdata.data.upperlimit.useddvariablevalue
    ulEditCtrlStatus.enable = 'inactive';
end

% UserData = get(Children.limitScaleButton, 'UserData');
% limitScaleButtonCtrlStatus = UserData.ctrlStatus;
data = dlgdata.data;
simulatedLabelCtrlStatus.string = ['of ' field];
if ~strcmp(data.(field).class, 'default')
    if ~isempty(constraint)
        minstr = sprintf('%0.6g', constraint);
        maxstr = sprintf('%0.6g', constraint);
    else
        minstr = 'n.a.';
        maxstr = 'n.a.';
    end
    simulatedLabelCtrlStatus.enable = 'on';
    upperSimulatedValueCtrlStatus.string = maxstr;
    lowerSimulatedValueCtrlStatus.string = minstr;
    limitScaleButtonCtrlStatus.enable = flag2str(dlgdata.bIsFullVs & ...
        bCompliant & ~isnan(constraint) & ~isinf(constraint) & ...
        ds_isa(['/Pool/Typedefs/' data.(field).type], 'integertype'));
else
    simulatedLabelCtrlStatus.enable = 'off';
    limitScaleButtonCtrlStatus.enable = 'off';
    lowerSimulatedValueCtrlStatus.string = '';
    upperSimulatedValueCtrlStatus.string = '';
end

ulEditCtrlStatus.string = data.upperlimit.value;
llEditCtrlStatus.string = data.lowerlimit.value;
selectPopupCtrlStatus.value = selectIdx;

% save dialog data to UserData properties
ctrlsList = {'ulEdit', 'llEdit', 'limitScaleButton', 'selectPopup', ...
    'simulatedLabel', 'lowerSimulatedValue', 'upperSimulatedValue', ...
    'llDDValueCheckbox', 'ulDDValueCheckbox'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

% set controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLSetCtrlsStatus(dlgfig, Children, ctrlsList([1:4,8,9]));
